import os
import math
import pickle
import numpy
from scipy import interpolate
from CalTorqueGEDIT import OpenCalTorqueXLS, GetSheetData
from AverageTorqueIN import AverageTorqueInterp
from lmfit import minimize, Parameters	
													# Will then have to seperate into in and out
#_________________________________________________________________________ Get data
datapath = 'dataGEDIT/'
lsdir = os.listdir(datapath)

for f in lsdir:
   if (f.split('.')[-1] not in ['xlsx', 'xls']):
      continue
   print f
   book = OpenCalTorqueXLS(datapath+f)
   data = GetSheetData(book)

#_________________________________________________________________________ Get pickled averages
def AverageTorqueInterp(x):
	file = open('pickled_average_in.pkl', 'rb')
	avgdata = pickle.load(file)
	file.close()
	
	Xavg = avgdata['x']
	Yavg = avgdata['y']
	
	f = interpolate.interp1d(Xavg, Yavg)

	return f(x)

#__________________________________________________________________________ Minimize residual
### Goal: minimize residual by varying x (position)

#____retrieve data to be fitted____#
x = numpy.array(data['position'])	# variable to vary

xfilt = []							# discard x values that ar out of interp. range
for j in x:
	if j >= 0 and j < 400:
		xfilt.append(j)
xfilt = numpy.array(xfilt)


y1 = data['torque_inoz'] 			# gets run y values associated to undiscarded x values
data = []
for i, k in enumerate(x):
	if k >= 0 and k < 400:
		data.append(y1[i])
data = numpy.array(data)


#___define objective function: returns array to be minimized___#

def Residual(params, xfilt, data):
	# model - interpolated torque values, subtract data
	# Unpaking parameters:
	position = params['position'].value		### parameters for the model. I don't think second one is needed
	#torque = params['torque'].value


	model = AverageTorqueInterp(position) 	### position or xfilt?
	return model - data


#___create a set of parameters___#
params = Parameters()
params.add('position', value = xfilt)		### Right parameters? Probs not
#params.add('torque', value = AverageTorqueInterp(xfilt), vary = False)

result = minimize(Residual, params, args = (xfilt, data))		# ValueError: object too deep for desired array


#___calculate final result___#
#final = x - result.residual		# plus or minus?


	# might have to re-interpolate
	# get offset and get graphs to shift by doing x - offset
	# residue as function of offset





#______________________________________________________Manually getting least squares
#def Residual():							### maybe have to modify this function to minimize
#	y1 = data['torque_inoz']			#want to minimise by varying x1... 
#	x1 = data['position']
#	x1b = []
#	y2 = []
#	for x in data['position']:
#		if x >= 0 and x < 400:
#			x1b.append(x)
	### if x[i] not appended, y1.remove(y[i])
#	for i, thing in enumerate(x1):
#		if x1[i] not in x1b:
#			y1.remove(y1[i])
#	x1b.sort()
#	y1b = numpy.array(y1)
#	x1c = numpy.array(x1b)
#	y2.append(AverageTorqueInterp(x1c))
#	LstSqr = math.sqrt(numpy.sum(numpy.power(y1b - y2, 2)))
#	return LstSqr								# How to minimize this now?



####NOTES
	#positional args use - pass in other data needed to calculate the residual(data array, dependant variable, uncertainties,etc..)
	#### there are different fitting methods to chose from
	#There is a way to include uncertainties - errorbars - in this

####OPTIONS
# scipy.optimize.minimize
# limfit minimize
